home *** CD-ROM | disk | FTP | other *** search
Text File | 1999-05-28 | 28.8 KB | 1,305 lines |
- *
- * pronet.device
- *
-
- VERSION equ 38
- REVISION equ 1
-
- ******* pronet.device/--Overview-- ******************************************
- *
- * IMPORTANT: Everything in here is subject to change. This is a "private"
- * device, but I've documented it nevertheless. Don't expect your programs
- * to run with future versions of the device!
- *
- * >> GENERAL INFORMATION <<
- *
- * The device is able to handle several Units, which are defined in the
- * `devs:pronet/.config' file. Each Unit corresponds to a certain driver
- * and interface. The Units are subdivided into Ports, which are channels
- * between two sides of one Unit. This way two application systems may work
- * through the same connection without interfering each other.
- *
- * pronet.device is *not* a SANA-II compliant networking device, and it is not
- * compatible to any other exec device, because it's got some very strange
- * behaviour regarding incoming data. Sometimes it is useful, sometimes it is
- * not, but I will not change this anyway: CMD_READ is not supported, instead
- * of that, when opening the device, you specify a MsgPort to which all
- * incoming data will be sent automatically, if you want it or not!
- *
- * pronet.device v37 is incompatible to ProNET applications written
- * earlier, see below. I'm sorry for that, but I've not heard from people
- * using this device anyway ;-)
- *
- * >> ERROR CODES <<
- *
- * pronet.device v37 can return one of the following error codes after
- * OpenDevice():
- *
- * PNDERR_PORTEXISTS
- * You've tried to open up a Port which is already in use.
- *
- * PNDERR_DRIVERTROUBLE
- * The driver of the Unit you requested can not be started.
- * You can request a more detailed error message by setting the
- * according bit in OpenDevice()/Flags. pnr_Data must then point to
- * a buffer provided by you. The string will not exceed 63 characters
- * plus the terminating zero. If no error occurs, the buffer will
- * not be changed!
- *
- * PNDERR_UNIT_NOT_DEFINED
- * The Unit you requested is missing a definition in the config file.
- *
- * >> CHANGES SINCE V3 <<
- *
- * v37: Write doesn't support two chunks anymore, Write can fail
- * with PNDERR_DESTINATION_GONE now, no more #?ConfigString() in order
- * to keep the configuration file tidy. Structure of received data
- * has changed. PNB_ERRORSTRING.
- *
- * >> WRITING DRIVERS <<
- *
- * You find information on this subject in the other autodoc file supplied
- * with the ProNET distribution.
- *
- *****************************************************************************
- *
- *
-
- include "A:OSmacros.i"
- include "exec/exec.i"
- include "dos/dosextens.i"
- include "devices/timer.i"
- include "P:include/devices/pronet.i"
- include "exec_lib.i"
- include "dos_lib.i"
-
- moveq #-1,d0
- rts
-
- STRUCTURE MyDev,LIB_SIZE *** Device Base
- APTR pnd_SegList ;Segment List
- APTR pnd_UnitList ;List of all Units
- STRUCT pnd_Semaphore,SS_SIZE ;for Single-Threading DevOpen()
- LABEL pnd_SizeOf
-
- STRUCTURE MyUnit,0 *** Unit Structure
- APTR pndu_Next
- ULONG pndu_Number
- UWORD pndu_OpenCnt
-
- APTR pndu_ProcName
- APTR pndu_ProcessID
-
- APTR pndu_SysBase
- APTR pndu_DOSBase
- UWORD pndu_RC
-
- APTR pndu_MsgPort
- APTR pndu_MsgBackPort
- APTR pndu_PortList
-
- APTR pndu_ConfigString
- STRUCT pndu_DriverName,30
- BPTR pndu_DriverSeg
-
- STRUCT pndu_DriverData,pndd_Size
-
- STRUCT pndu_PendingReads,12
- STRUCT pndu_PendingWrites,12
- LABEL pndu_SizeOf
-
- STRUCTURE PortMember,0 *** One Port of a Unit
- APTR pndp_Next
- UWORD pndp_Number
- ULONG pndp_MsgPort
- LABEL pndp_SizeOf
-
- PNDCMD_ADDPORT equ CMD_NONSTD+4
- PNDCMD_REMPORT equ CMD_NONSTD+5
-
- LibResident dc.w RTC_MATCHWORD
- dc.l LibResident
- dc.l EndResident
- dc.b RTF_AUTOINIT
- dc.b VERSION
- dc.b NT_DEVICE
- dc.b 0
- dc.l DevName
- dc.l IDString
- dc.l LibInitData
-
- DevName dc.b "pronet.device",0
- dc.b "$VER: "
- IDString dc.b "pronet.device "
- dc.b (VERSION/10)+48,(VERSION-((VERSION/10)*10))+48,".",REVISION+48
- dc.b " (28.5.99)",13,10,0
- even
-
- LibInitData dc.l pnd_SizeOf
- dc.l FuncTab
- dc.l DataTab
- dc.l Init
-
- FuncTab dc.l Open
- dc.l Close
- dc.l Expunge
- dc.l ExtFunc
- dc.l BeginIO
- dc.l AbortIO
- dc.l -1
-
- DataTab INITBYTE LN_TYPE,NT_DEVICE
- INITLONG LN_NAME,DevName
- INITBYTE LIB_FLAGS,LIBF_SUMUSED!LIBF_CHANGED
- INITWORD LIB_VERSION,VERSION
- INITWORD LIB_REVISION,REVISION
- INITLONG LIB_IDSTRING,IDString
- dc.w 0
-
- OurBase dc.l 0
-
- *****i* pronet.device/DevInit ***********************************************
- *
- * NAME
- * DevInit -- Device is initialized after being loaded into memory.
- *
- * FUNCTION
- * This function used to perform a keyfile check. Not any longer.
- *
- *****************************************************************************
- *
- * d0 is *OurBase, a0 is *SegList
- * must return NULL for error or *SegList for OK.
-
- Init movem.l d1-d7/a0-a6,-(sp)
- move.l d0,a5
- move.l a5,OurBase
- move.l a0,pnd_SegList(a5)
-
- move.l a5,a4 ;Device startupped correctly
-
- * We need this SignalSemaphore to artificially single-thread our Open
- * routine, because we break the exec single-threading by WaitIO.
- lea pnd_Semaphore+SS_SIZE(a5),a0
- moveq #SS_SIZE/2-1,d0
- .clrsema clr.w -(a0)
- dbra d0,.clrsema
- LIBCALL InitSemaphore
-
- move.l a4,d0
- movem.l (sp)+,d1-d7/a0-a6
- rts
-
- dc.l $0BADD00D
-
- ******* pronet.device/OpenDevice ********************************************
- *
- * NAME
- * OpenDevice -- Open up a new port of a certain ProNET Unit.
- *
- * SYNOPSIS
- * error = OpenDevice("pronet.device", unit, ioRequest, flags);
- * D0 A0 D0 A1 D1
- *
- * BYTE OpenDevice(STRPTR, ULONG, struct PNRequest*, ULONG);
- *
- * FUNCTION
- * This is an exec.library call.
- *
- * Hey, what do you think it does?!??
- *
- * INPUTS
- * unit - This number must be defined in the `DEVS:ProNET/.config' file,
- * otherwise OpenDevice() will return PNDERR_UNIT_NOT_DEFINED.
- * ioRequest - A pointer to an initialized (see below) PNRequest block.
- * flags - As described in the overview page, you have the option
- * to get extensive error messages when setting a bit here.
- * The bit is defined as PNB_ERRORSTRING (the PNF_ definition also
- * exists).
- *
- * Two components of the PNRequest must be initialized before calling
- * OpenDevice():
- *
- * pnr_MsgPort - pointer to a MsgPort where incoming data is sent to.
- * pnr_NetSourcePort - The port number you want to open.
- *
- * RESULT
- * error - zero if everything went o.k., otherwise an error code
- * as defined in exec/errors.h or devices/pronet.h.
- *
- * NOTES
- * The *one and only* valid port numbers are 0x0001 to 0x7fff. If you
- * want a special number above 0x7fff reserved for your application,
- * please contact me!
- *
- * If you don't have any special preferences for your port number,
- * you can use PNP_NEXTFREE to let pronet.device assign you the next
- * free one (it will be put into pnr_NetSourcePort then).
- *
- *****************************************************************************
- *
-
- Open movem.l a2-a6/d2-d7,-(sp)
- ; Any AllocMem could call our Expunge vector, so prevent that by faking
- ; an opener!
- addq.w #1,LIB_OPENCNT(a6)
-
- move.l d0,d6 ;Unit
- move.l a1,a2 ;IORequest
- move.l a6,a5 ;DevBase
- move.l d1,pnr_Length(a2)
- move.l 4.w,a6
-
- * We do this so that InitUnit can modify OurBase->pnd_UnitList without
- * danger. Forbid/Permit sucks...
- lea pnd_Semaphore(a5),a0
- LIBCALL ObtainSemaphore
-
- move.b #IOERR_OPENFAIL,IO_ERROR(a2)
-
- * Does the required Unit already exist?
- lea pnd_UnitList(a5),a3
- .searchunit move.l (a3),d0
- beq.s .newunit
- move.l d0,a3
- cmp.l pndu_Number(a3),d6
- bne.s .searchunit
- bra.s .unitok
-
- * No! So create a Unit!
- .newunit bsr InitUnit
- tst.l d0
- beq.s .ende
- move.l d0,a3
-
- * Yes! Add new port now! Unit-Structure in a3
- .unitok move.w #PNDCMD_ADDPORT,IO_COMMAND(a2)
- move.l a2,a1
- move.l pndu_MsgPort(a3),a0
- LIBCALL PutMsg
- move.l a2,a1
- LIBCALL WaitIO
- tst.b d0
- bne.s .ende
-
- move.l a3,IO_UNIT(a2)
- addq.w #1,pndu_OpenCnt(a3)
-
- * Device successfully opened.
- bclr #LIBB_DELEXP,LIB_FLAGS(a5)
- addq.w #1,LIB_OPENCNT(a5)
- move.b #NT_REPLYMSG,LN_TYPE(a2)
- clr.b IO_ERROR(a2)
-
- .ende lea pnd_Semaphore(a5),a0
- LIBCALL ReleaseSemaphore
-
- subq.w #1,LIB_OPENCNT(a5)
- move.b IO_ERROR(a2),d0
- beq.s .0
- move.l #-1,IO_DEVICE(a2)
- move.l #-1,IO_UNIT(a2)
- .0 movem.l (sp)+,a2-a6/d2-d7
- rts
-
- ; -- Create new Unit
- InitUnit ; a5 *DevBase
- ; a2 *IORequest
- ; d6 Unit
- ; RETURNS d0 *Unit-Structure or NULL
- moveq #0,d7
-
- move.l 4.w,a6
- lea dosname(pc),a1
- moveq #0,d0
- LIBCALL OpenLibrary
- move.l d0,d5
- beq .nodos
-
- move.l #pndu_SizeOf,d0
- move.l #MEMF_PUBLIC!MEMF_CLEAR,d1
- LIBCALL AllocMem
- tst.l d0
- beq .nomem1
- move.l d0,a3
-
- move.l d6,pndu_Number(a3)
-
- moveq #32,d0
- move.l #MEMF_PUBLIC,d1
- LIBCALL AllocMem
- tst.l d0
- beq.s .nomem2
- move.l d0,a4
-
- move.l a4,pndu_ProcName(a3)
-
- move.l d6,-(sp)
- pea FormatString(pc)
- move.l a4,-(sp)
- bsr _mysprintf
- add.w #12,sp
-
- * First, create Unit process
- move.l d5,a6
- move.l a4,d1
- moveq #0,d2
- move.l #ProcessCode-4,d3
- lsr.l #2,d3
- move.l #4096,d4
- LIBCALL CreateProc
- move.l d0,pndu_ProcessID(a3)
- beq.s .noprocess
-
- * Notify process about Unit number, this is the only message we send
- * to the Process MsgPort, all the others from BeginIO go to a new MsgPort
- * that is created while the Process' initialization.
- move.l 4.w,a6
- move.l a2,a1
- move.l a3,IO_UNIT(a1)
- clr.b IO_FLAGS(a1)
- move.l d0,a0
- LIBCALL PutMsg
-
- * Wait for Process to finish initialization
- move.l a2,a1
- LIBCALL WaitIO
- tst.b d0
- bne.s .noprocess
-
- * Now add this Unit-Structure to our internal List!!
- lea pnd_UnitList(a5),a0
- move.l (a0),(a3)
- move.l a3,(a0)
- move.l a3,d7
- bra.s .nomem1
-
- .noprocess move.l 4.w,a6
- move.l a4,a1
- moveq #32,d0
- LIBCALL FreeMem
- .nomem2 move.l a3,a1
- move.l #pndu_SizeOf,d0
- LIBCALL FreeMem
- .nomem1 move.l d5,a1
- LIBCALL CloseLibrary
- .nodos move.l d7,d0
- rts
-
- ******* pronet.device/CloseDevice *******************************************
- *
- * NAME
- * CloseDevice -- Close a port of a certain ProNET Unit.
- *
- * SYNOPSIS
- * CloseDevice(PNRequest);
- * A1
- *
- * FUNCTION
- * This is an exec.library call.
- *
- * This function terminates access to the corresponding ProNET Unit.
- * Since the Unit is not shut down automatically, even if you were
- * the last user of it, a RemDevice() would be the right thing to
- * do after closing pronet.device.
- *
- * INPUTS
- * PNRequest - A pointer to a previously opened ProNET IO Request.
- *
- * EXAMPLE
- * This code can force a specified device to try and expunge.
- * Of course, if the device is in use nothing will happen:
- *
- * void FlushDevice(name)
- * char *name;
- * {
- * struct Device *result;
- *
- * Forbid();
- * if(result=(struct Device *)FindName(&SysBase->DeviceList,name))
- * RemDevice(result);
- * Permit();
- * }
- *
- * SEE ALSO
- * exec.library/CloseDevice(), exec.library/RemDevice()
- *
- *****************************************************************************
- *
- *
-
- Close movem.l a2/a5,-(sp)
- move.l a1,a2
- move.l a6,a5
-
- move.l 4.w,a6
- move.l IO_UNIT(a1),a0
- subq.w #1,pndu_OpenCnt(a0)
- move.l pndu_MsgPort(a0),a0
- move.w #PNDCMD_REMPORT,IO_COMMAND(a1)
- LIBCALL PutMsg
- move.l a2,a1
- LIBCALL WaitIO
-
- move.l a2,a1
- move.l a5,a6
- move.l #-1,IO_DEVICE(a1)
- move.l #-1,IO_UNIT(a1)
-
- subq.w #1,LIB_OPENCNT(a6)
- moveq #0,d0
- movem.l (sp)+,a2/a5
- rts
-
- ; -- This routine was kept free by Commodore for about 10 years now ;)
- ExtFunc moveq #0,d0
- rts
-
- *****i* pronet.device/BeginIO ***********************************************
- *
- * NAME
- * BeginIO -- Execute a device command.
- *
- * FUNCTION
- * This is an exec.library call.
- *
- * We don't support any QUICK operations, so this bit is cleared
- * in any case.
- *
- *****************************************************************************
- *
- *
-
- BeginIO move.l a6,-(sp)
- move.b #NT_MESSAGE,LN_TYPE(a1)
- bclr #IOB_QUICK,IO_FLAGS(a1)
- clr.b IO_ERROR(a1)
- move.l IO_UNIT(a1),a0
- move.l pndu_MsgPort(a0),a0
- move.l 4.w,a6
- LIBCALL PutMsg
- move.l (sp)+,a6
- rts
-
- *****i* pronet.device/AbortIO ***********************************************
- *
- * NAME
- * AbortIO -- Abort a currently queued IO request.
- *
- * FUNCTION
- * This is an exec.library call.
- *
- * Sorry folks, we don't support AbortIO.
- *
- *****************************************************************************
- *
- *
-
- AbortIO moveq #0,d0 ;Gar nix geht ab hier.
- rts
-
- *****i* pronet.device/Expunge ***********************************************
- *
- * NAME
- * Expunge -- Prepare device removal.
- *
- * FUNCTION
- * This is an exec.library call.
- *
- * We return *SegList if the device can be deallocated or NULL if we
- * have still openers.
- *
- * Even if we have openers, we try to get rid of all unused Units.
- *
- *****************************************************************************
- *
- *
-
- Expunge movem.l d2-d7/a2-a6,-(sp)
-
- move.l a6,a5
- move.l 4.w,a6
-
- sub.l a1,a1
- LIBCALL FindTask
- move.l d0,expungetask
-
- moveq #-1,d0
- LIBCALL AllocSignal
- move.b d0,expungesignal
- move.b d0,d7
- bmi.s .delexp
-
- lea pnd_UnitList(a5),a3
- .browseunits move.l a3,a4 ;a4=lastpt
- move.l (a3),d0
- .browseunitse beq.s .nomoreunits
- move.l d0,a3 ;a3=current
-
- tst.w pndu_OpenCnt(a3)
- bne.s .browseunits
-
- move.l pndu_ProcessID(a3),a1
- lea -pr_MsgPort(a1),a1
- move.l #SIGBREAKF_CTRL_C,d0
- LIBCALL Signal
-
- moveq #0,d0
- bset d7,d0
- LIBCALL Wait
-
- move.l pndu_ProcName(a3),a1
- moveq #32,d0
- LIBCALL FreeMem
-
- move.l (a3),d2
- move.l d2,(a4)
- move.l a3,a1
-
- move.l #pndu_SizeOf,d0
- LIBCALL FreeMem
- move.l d2,d0
- bra.s .browseunitse
-
- .nomoreunits move.b d7,d0
- LIBCALL FreeSignal
- tst.w LIB_OPENCNT(a5)
- beq.s .expunge
- .delexp moveq #0,d0
- bset #LIBB_DELEXP,LIB_FLAGS(a6)
- bra.s .ende
-
- .expunge move.l pnd_SegList(a5),d2 ;The whole Device is not used,
- move.l a5,a1 ;so quit everything!
- LIBCALL Remove
- move.l a5,a1
- moveq #0,d0
- move.w LIB_NEGSIZE(a5),d0
- sub.l d0,a1
- add.w LIB_POSSIZE(a5),d0
- LIBCALL FreeMem
-
- move.l d2,d0
- .ende movem.l (sp)+,d2-d7/a2-a6
- rts
-
- expungetask dc.l 0
- expungesignal dc.b 0,0
-
- ** -----------------------------------------------------------------------
- **
- **
- **
- **
-
- **
- ** DeviceUnit Process Code
- **
-
- **
- **
- **
- **
- ** -----------------------------------------------------------------------
-
- cnop 0,4
-
- * First we will receive the first requestor's IORequest as a startup
- * message. It contains the Unit structure in IO_UNIT. We must init
- * and return with an error code in IO_ERROR.
-
- ProcessCode move.l 4.w,a6
- sub.l a1,a1
- LIBCALL FindTask
- move.l d0,a2
- lea pr_MsgPort(a2),a2
- move.l a2,a0
- LIBCALL WaitPort
- move.l a2,a0
- LIBCALL GetMsg
- move.l d0,a3
-
- move.b #IOERR_OPENFAIL,IO_ERROR(a3) ;[a3] Startupmsg
- move.l IO_UNIT(a3),a5
- st pndu_RC(a5)
-
- * Get Library Bases. We do *not* do it once in DevInit, but for every
- * new process, since all this shit could (and will) change with PowerPC.
- move.l a6,pndu_SysBase(a5)
- lea dosname(pc),a1
- moveq #0,d0
- LIBCALL OpenLibrary
- move.l d0,pndu_DOSBase(a5)
- beq .nodos
-
- lea pndu_PendingReads(a5),a1
- NEWLIST a1
- lea pndu_PendingWrites(a5),a1
- NEWLIST a1
-
- * Get port for messages replied from the applications
- bsr CreatePort
- move.l d0,pndu_MsgBackPort(a5)
- beq .noport
-
- * Get new port for all the messages arriving from BeginIO()
- bsr CreatePort
- move.l d0,pndu_MsgPort(a5)
- beq .noport2
-
- * Get configuration string for our Unit
- move.l pndu_Number(a5),d0
- bsr getconfigstr
- move.b #PNDERR_UNIT_NOT_DEFINED,IO_ERROR(a3)
- move.l d0,pndu_ConfigString(a5)
- beq.s .noconf
-
- * Load and start the driver
- move.b #PNDERR_DRIVERTROUBLE,IO_ERROR(a3)
- bsr StartDriver
- tst.l d0
- bne.s .nodriver
-
- * Everything went O.K. -> Push back the startup packet and start working!
- clr.b IO_ERROR(a3)
- move.l a3,a1
- LIBCALL ReplyMsg
-
- clr.w pndu_RC(a5)
-
- bsr MainLoop
-
- bsr StopDriver
- .nodriver move.l pndu_ConfigString(a5),a0
- bsr freeconfigstr
- .noconf move.l pndu_MsgPort(a5),a0
- bsr DeletePort
- .noport2 move.l pndu_MsgBackPort(a5),a0
- bsr DeletePort
- .noport move.l pndu_DOSBase(a5),a1
- move.l 4.w,a6
- LIBCALL CloseLibrary
- .nodos tst.w pndu_RC(a5)
- beq.s .returnfinal
- LIBCALL Forbid ;Use Forbid() to prevent Exec from a task change
- move.l a3,a1 ;between ReplyMsg and the complete discard of the
- LIBJMP ReplyMsg ;process!
-
- .returnfinal LIBCALL Forbid
- move.l expungetask(pc),a1
- moveq #0,d0
- move.b expungesignal(pc),d1
- bset d1,d0
- LIBJMP Signal
-
- * These routines handle the configuration file:
-
- ; -- Obtain configuration string
- getconfigstr ; d0 number (0..n)
- ; a5 *pndu
- ; RETURNS d0 *line-string or NULL if it doesn't exist
- movem.l d2-d7/a2-a6,-(sp)
- move.l d0,a2
- moveq #0,d4 ;[d4] RC
-
- * Read Config File
- move.l pndu_DOSBase(a5),a6
- move.l #configname,d1
- move.l #MODE_OLDFILE,d2
- LIBCALL Open
- move.l d0,d7
- beq .nofile
-
- move.l d7,d1
- moveq #0,d2
- move.l #OFFSET_END,d3
- LIBCALL Seek
- move.l d7,d1
- moveq #0,d2
- move.l #OFFSET_BEGINNING,d3
- LIBCALL Seek
-
- addq.l #1,d0
- move.l d0,d5 ;[d5] configmemsize
- move.l #MEMF_CLEAR,d1
- move.l pndu_SysBase(a5),a6
- LIBCALL AllocMem
- tst.l d0
- beq .nomem
- move.l d0,a3 ;[a3] configmem
- move.l d0,a4
-
- move.l d7,d1
- move.l a3,d2
- move.l d5,d3
- subq.l #1,d3
- move.l pndu_DOSBase(a5),a6
- LIBCALL Read
- cmp.l d0,d3
- bne.s .readerr
-
- * Now search the line ID
- move.l a2,d2
- .loop subq.w #1,d2
- bcc.s .next
-
- * Get string length
- move.l a3,a0
- .getlen move.b (a0)+,d0
- cmp.b #32,d0
- bcc.s .getlen
- sub.l a3,a0
- move.l a0,d0
- subq.l #1,d0
- beq.s .readerr
-
- * Copy string
- move.w d0,d2
- addq.l #5,d0 ;EOS + Length Tracking
- move.l d0,d3
- move.l pndu_SysBase(a5),a6
- moveq #MEMF_PUBLIC,d1
- LIBCALL AllocMem
- tst.l d0
- beq.s .readerr
-
- move.l d0,a0
- move.l d3,(a0)+
- move.l a0,d4
- subq.w #1,d2
- .copy move.b (a3)+,(a0)+
- dbra d2,.copy
- clr.b (a0)+
- bra.s .readerr
-
- * Jump to next line
- .next move.b (a3)+,d0
- beq.s .readerr
- cmp.b #10,d0
- beq.s .loop
- bra.s .next
-
- .readerr move.l a4,a1
- move.l d5,d0
- move.l pndu_SysBase(a5),a6
- LIBCALL FreeMem
-
- .nomem move.l d7,d1
- move.l pndu_DOSBase(a5),a6
- LIBCALL Close
-
- .nofile move.l d4,d0
- .ende movem.l (sp)+,d2-d7/a2-a6
- rts
-
- ; -- Dispose configuration string
- freeconfigstr ; a0 *line-string got by 'getconfigstr'
- move.l a6,-(sp)
- move.l -(a0),d0
- move.l a0,a1
- move.l pndu_SysBase(a5),a6
- LIBCALL FreeMem
- move.l (sp)+,a6
- rts
-
- ; -- Load the interface driver and initialize it.
- StartDriver ; RETURNS d0 <>NULL on failure!
- movem.l a2/a6,-(sp)
- lea pndu_DriverName(a5),a1
- lea driverpath(pc),a0
- .l0 move.b (a0)+,(a1)+
- bne.s .l0
-
- subq.l #1,a1
- move.l a1,a2
- move.l pndu_ConfigString(a5),a0
- .l1 move.b (a0)+,d0
- move.b d0,(a1)+
- cmp.b #" ",d0
- bhi.s .l1
- clr.b -(a1)
- move.l a0,d6
-
- move.l pndu_DOSBase(a5),a6
- lea pndu_DriverName(a5),a1
- move.l a1,d1
- LIBCALL LoadSeg
- move.l d0,pndu_DriverSeg(a5) ;(a5) was missing in V2 & V3 -> Enforcer hit!
- bne.s .c1
- move.l #mc_err3,d0
- bra.s .0000
- .c1 add.l d0,d0
- add.l d0,d0
- addq.l #4,d0
- move.l d0,a2
-
- * And now, Ladies & Gentlemen :))
- lea pndu_DriverData(a5),a0
- move.l d6,a1 ;ConfString after Driver-ID
- move.l #"RST!",d0
- moveq #2,d1 ;ProNET >V3
- jsr (a2)
- tst.l d0
- beq.s .ende
-
- * Copy the extensive error message when requested.
- .0000 btst #PNB_ERRORSTRING,pnr_Length+3(a3)
- beq.s .error2
- cmp.l #PNDRVERR_NO_MEMORY,d0
- bne.s .000
- move.l #mc_err1,d0
- .000 cmp.l #PNDRVERR_WRONG_ARGS,d0
- bne.s .001
- move.l #mc_err2,d0
- .001 move.l d0,a0
-
- move.l pnr_Data(a3),a1
- moveq #62,d0
- .00cpy move.b (a0)+,(a1)+
- dbeq d0,.00cpy
- clr.b (a1)+
-
- .error2 move.l pndu_DOSBase(a5),a6
- move.l pndu_DriverSeg(a5),d1
- beq.s .error
- LIBCALL UnLoadSeg
-
- .error moveq #-1,d0
- .ende movem.l (sp)+,a2/a6
- rts
-
- ; -- Cancel the interface driver
- StopDriver move.l pndu_DriverData+pndd_Exit(a5),a0
- jsr (a0)
-
- move.l pndu_DOSBase(a5),a6
- move.l pndu_DriverSeg(a5),d1
- LIBCALL UnLoadSeg
- rts
-
- ******************
- ; -- The Main Loop
- ******************
-
- MainLoop
- move.l pndu_MsgBackPort(a5),a0
- move.b MP_SIGBIT(a0),d2
- move.b pndu_DriverData+pndd_ReadSignalBit(a5),d3
- move.l pndu_MsgPort(a5),a0
- move.b MP_SIGBIT(a0),d4
- moveq #0,d5
- bset #SIGBREAKB_CTRL_C,d5
- bset d2,d5
- bset d3,d5
- bset d4,d5 ;[d5] Signalmask to wait for
- movem.l a6/d2-d5,-(sp)
-
- Wait4Msg movem.l (sp),a6/d2-d5
- bsr CheckWrites
- move.l d5,d0
- LIBCALL Wait
- btst #SIGBREAKB_CTRL_C,d0
- bne.s StopThisShit
- movem.l d0/d3/d4,-(sp)
- btst d2,d0
- bne MessageBack
- wait1 movem.l (sp),d0/d3/d4
- btst d3,d0
- bne ReceiveData
- wait2 movem.l (sp)+,d0/d3/d4
- btst d4,d0
- bne MessageLoop
- bra Wait4Msg
- StopThisShit movem.l (sp)+,a6/d2-d5
- rts
-
- ; -- Look at the history, 31-05-95 for reasons why we do this!
- CheckWrites
- lea pndu_PendingWrites(a5),a0
- TSTLIST a0
- beq.s .okay
- move.b pndu_DriverData+pndd_ReadSignalBit(a5),d0
- moveq #0,d1
- bset d0,d1
- moveq #-1,d0
- LIBCALL SetSignal
- .okay rts
-
- *****i* pronet.device/ReceiveData *******************************************
- *
- * NAME
- * ReceiveData -- read incoming data from driver.
- *
- *****************************************************************************
- *
- *
-
- ******* pronet.device/ReceivedData ******************************************
- *
- * Received data will be sent to the MsgPort you specified in pnr_MsgPort
- * when opening the device. You can not change it after opening.
- * mn_Length, as opposed to pre-v37, contains the length of the whole Message
- * structure. The first word of mn_Node.ln_Name contains the source ProNET
- * Port, the second word contains the destination port. The data comes behind
- * the Message structure.
- *
- * This Message must be replied as soon as there is no use for it any more.
- *
- * If there is incoming data but pronet.device can't allocate the Message
- * structure, the packet is lost!
- *
- *****************************************************************************
- *
- *
-
- ReceiveData
- move.l pndu_DriverData+pndd_ReadQuery(a5),a0 ;Do external driver magic..
- jsr (a0)
-
- * d0.w length (if NULL then exit!!!)
- * d1 destination port
- * d2 source port
- ext.l d0
- beq .ende
- move.w d1,d7
- move.w d2,d5
- add.l #MN_SIZE,d0
- move.l d0,d6
-
- .tryagain moveq #MEMF_PUBLIC,d1
- LIBCALL AllocMem
- tst.l d0
- bne.s .memok
-
- * No memory! Forget it! (ProNET <=V3 would busy wait until
- * memory is free. This was BAD!)
- move.l pndu_DriverData+pndd_ReadFlush(a5),a0
- jsr (a0)
- bra.s .ende
-
- * Now get the data and build a Message
- .memok move.l d0,a3
- lea MN_SIZE(a3),a0
- move.l pndu_DriverData+pndd_Read(a5),a1
- jsr (a1)
- move.w d5,LN_NAME(a3)
- move.w d7,LN_NAME+2(a3)
- move.w d6,MN_LENGTH(a3)
- move.l pndu_MsgBackPort(a5),MN_REPLYPORT(a3)
- move.b #NT_MESSAGE,LN_TYPE(a3)
-
- lea pndu_PendingReads(a5),a0
- move.l a3,a1
- LIBCALL AddTail
-
- .ende bsr TryPendingReads
- bsr TryPendingWrites
- bra wait2
-
- *****i* pronet.device/MessageLoop *******************************************
- *
- * NAME
- * MessageLoop -- process applications' commands.
- *
- * FUNCTION
- * We got a new request from one of our clients.. well we could say we
- * are currently busy but then he would use ParNet ;-)
- *
- *****************************************************************************
- *
- *
-
- MessageLoop
- move.l pndu_MsgPort(a5),a0
- LIBCALL GetMsg
- tst.l d0
- beq Wait4Msg ;no more messages
- move.l d0,a2
- move.w IO_COMMAND(a2),d0
-
- cmp.w #CMD_WRITE,d0
- beq CMD__WRITE
- cmp.w #PNDCMD_ADDPORT,d0
- beq CMD__ADDPORT
- cmp.w #PNDCMD_REMPORT,d0
- beq CMD__REMPORT
-
- move.b #IOERR_NOCMD,IO_ERROR(a2)
- move.l a2,a1
- LIBCALL ReplyMsg
- bra MessageLoop
-
- *****i* pronet.device/CMD_ADDPORT *******************************************
- *
- * NAME
- * AddPort -- New device opener.
- *
- *****************************************************************************
- *
- *
-
- CMD__ADDPORT
- move.w pnr_NetSourcePort(a2),d1
- cmp.w #PNP_NEXTFREE,d1
- bne.s .0
- moveq #1,d1
- lea pndu_PortList(a5),a1
- .next move.l a1,a0
- .loop1 move.l (a0),d0
- beq.s .notfound
- move.l d0,a0
- cmp.w pndp_Number(a0),d1
- bne.s .loop1
- addq.w #1,d1
- bra.s .next
- .notfound move.w d1,pnr_NetSourcePort(a2)
-
- .0 move.b #IOERR_OPENFAIL,IO_ERROR(a2)
-
- * See if port already exists, portnumber in d1 now
- lea pndu_PortList(a5),a0
- .loop0 move.l (a0),d0
- beq.s .ok
- move.l d0,a0
- cmp.w pndp_Number(a0),d1
- bne.s .loop0
- * Sorry
- move.b #PNDERR_PORTEXISTS,IO_ERROR(a2)
- bra.s .ende
-
- * No, add it!
- .ok moveq #pndp_SizeOf,d0
- moveq #0,d1
- LIBCALL AllocMem
- tst.l d0
- beq.s .ende
-
- move.l d0,a4
- move.w pnr_NetSourcePort(a2),pndp_Number(a4)
- move.l pnr_MsgPort(a2),pndp_MsgPort(a4)
- lea pndu_PortList(a5),a0
- move.l (a0),(a4)
- move.l a4,(a0)
-
- bsr TryPendingReads
-
- clr.b IO_ERROR(a2) ;Okay, port added
- .ende move.l a2,a1
- LIBCALL ReplyMsg
- bra MessageLoop
-
- *****i* pronet.device/CMD_REMPORT *******************************************
- *
- * NAME
- * RemPort -- Device is closed.
- *
- *****************************************************************************
- *
- *
-
- CMD__REMPORT
- move.w pnr_NetSourcePort(a2),d2
- lea pndu_PortList(a5),a1
- .find move.l a1,a3
- move.l (a1),d0
- beq.s .notfound
- move.l d0,a1
- cmp.w pndp_Number(a1),d2
- bne.s .find
- move.l (a1),d2
- moveq #pndp_SizeOf,d0
- LIBCALL FreeMem
- move.l d2,(a3) ;Teil aus der Liste entfernt !!
- move.l a2,a1
- LIBCALL ReplyMsg
- .notfound bra MessageLoop
-
- ******* pronet.device/CMD_WRITE *********************************************
- *
- * NAME
- * Write -- send output to ProNET Port.
- *
- * FUNCTION
- * This command causes a packet of data to be written out the ProNET
- * Port/Unit. The number of characters is specified in pnr_Length.
- *
- * IO REQUEST
- * io_Command - CMD_WRITE
- * pnr_Data - pointer to block of data to transmit
- * pnr_Length - number of characters to transmit. MUST BE EVEN AND MUST
- * NOT BE GREATER THAN 0x4000!
- *
- * RESULTS
- * io_Error - if the Write succeeded, then io_Error will be zero.
- * The only other possible error code is PNDERR_DESTINATION_GONE.
- *
- *****************************************************************************
- *
- *
-
- CMD__WRITE
- move.l a2,a1
- lea pndu_PendingWrites(a5),a0
- LIBCALL AddTail
- bsr TryPendingWrites
- bra MessageLoop ;kurz und schmerzlos :-)
-
- *****i* pronet.device/MessageBack *******************************************
- *
- * NAME
- * MessageBack -- Application replied a ProNET Message.
- *
- * FUNCTION
- * Free the message structure and data.
- *
- *****************************************************************************
- *
- *
-
- MessageBack
- move.l pndu_MsgBackPort(a5),a0
- LIBCALL GetMsg
- tst.l d0
- beq wait1
- move.l d0,a1
- moveq #0,d0
- move.w MN_LENGTH(a1),d0
- LIBCALL FreeMem
- bra.s MessageBack
-
- *****i* pronet.device/TryPendingReads *******************************************
- *
- * NAME
- * TryPendingReads -- Iterate through this Unit's pending reads list.
- *
- * FUNCTION
- * ProNET remembers all messages for ports that are not currently open
- * and sends them off when they are opened.
- *
- *****************************************************************************
- *
- *
-
- TryPendingReads
- move.l a2,-(sp)
- lea pndu_PendingReads(a5),a3
- move.l LH_HEAD(a3),a2
- addq.l #4,a3
- .looop cmp.l a2,a3
- bne.s .doit
- move.l (sp)+,a2
- rts
-
- .doit move.l a2,a4
- move.l LN_SUCC(a2),a2
-
- move.w LN_NAME+2(a4),d1
- lea pndu_PortList(a5),a0
- .find move.l (a0),d0
- beq.s .looop
- move.l d0,a0
- cmp.w pndp_Number(a0),d1
- bne.s .find
- move.l pndp_MsgPort(a0),d5
- move.l a4,a1
- LIBCALL Remove
- move.l d5,a0
- move.l a4,a1
- LIBCALL PutMsg
- bra.s .looop
-
- *****i* pronet.device/TryPendingWrites **************************************
- *
- * NAME
- * TryPendingWrites -- Process pending write requests.
- *
- * FUNCTION
- * This routine checks this Unit on unprocessed write requests and
- * sends them off if possible.
- *
- *****************************************************************************
- *
- *
-
- TryPendingWrites
- move.l a2,-(sp)
- lea pndu_PendingWrites(a5),a3
- move.l LH_HEAD(a3),a2
- addq.l #4,a3
- .looop cmp.l a2,a3
- bne.s .doit
- .busy move.l (sp)+,a2
- rts
-
- .doit move.l a2,a4
- move.l LN_SUCC(a2),a2
-
- .noxpk move.l pnr_Data(a4),a0
- move.l pnr_Length(a4),d0
- addq.l #1,d0 ;round up to word boundary
- bclr #0,d0
- move.w pnr_NetDestPort(a4),d1
- move.w pnr_NetSourcePort(a4),d2
- move.l pndu_DriverData+pndd_Write(a5),a6
- jsr (a6) ;Send the data
- move.l pndu_SysBase(a5),a6
- tst.w d0
- beq.s .okay
- bmi.s .busy
-
- * Remote machine doesn't respond, reply CMD_WRITE with
- * an error.
- move.l a4,a1
- LIBCALL Remove
- move.b #PNDERR_DESTINATION_GONE,IO_ERROR(a4)
- bra.s .reply
-
- .okay * IORequest done, reply it!
- move.l a4,a1
- LIBCALL Remove
- clr.b IO_ERROR(a4)
- .reply move.l a4,a1
- LIBCALL ReplyMsg
- bra .looop
-
- ** -----------------------------------------------------------------------
- **
- **
- **
- **
-
- **
- ** Useful routines
- **
-
- **
- **
- **
- **
- ** -----------------------------------------------------------------------
-
- _mysprintf movem.l a2/a3/a6,-(sp)
- move.l 4*4(sp),a3 ;Get the output string pointer
- move.l 5*4(sp),a0 ;Get the FormatString pointer
- lea 6*4(sp),a1 ;Get the pointer to the DataStream
- lea .stuffChar(pc),a2
- move.l 4.w,a6
- LIBCALL RawDoFmt
- movem.l (sp)+,a2/a3/a6
- rts
- .stuffChar move.b d0,(a3)+ ;Put data to output string
- rts
-
- include "P:include/devio_ports.s"
-
- dosname dc.b "dos.library",0
- configname dc.b "DEVS:ProNET/.config",0
- FormatString dc.b "pronet.device (%ld)",0
- driverpath dc.b "DEVS:ProNET/",0
- mc_err1 dc.b "Out of memory.",0
- mc_err2 dc.b "Wrong arguments in configuration file.",0
- mc_err3 dc.b "Can't find specified driver module.",0
- even
-
- EndResident:
-